package br.com.sales.generics.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNull;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;
import com.google.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author v
 */
public class HanRequestBuilder {

    @Inject
    public HanRequestBuilder() {
    }

    public JSONObject formatJson(Object value) {
        JSONValue newValue = toObjectJson(value);
        JSONObject obj = new JSONObject();
        obj.put("value", newValue == null ? JSONNull.getInstance() : newValue);
        return obj;
    }

    protected JSONArray toJSONArray(Object[] arrayOrigem) {
        if (arrayOrigem == null) {
            return null;
        }
        JSONArray arr = new JSONArray();
        int i = 0;
        for (Object val : arrayOrigem) {
            arr.set(i++, toObjectJson(val));
        }
        return arr;
    }

    protected JSONValue toObjectJson(Object entryValue) {
        if (entryValue instanceof JSONValue) {
            return (JSONValue) entryValue;
        } else if (entryValue instanceof JavaScriptObject) {
            return new JSONObject((JavaScriptObject) entryValue);
        } else if (entryValue instanceof String) {
            return new JSONString((String) entryValue);
        } else if (entryValue instanceof Number) {
            return new JSONNumber(((Number) entryValue).doubleValue());
        } else if (entryValue instanceof Map) {
            return convertMapToJsonObject((Map<String, Object>) entryValue);
        } else if (entryValue instanceof List) {
            return toJSONArray(((List) entryValue).toArray());
        }
        return JSONNull.getInstance();
    }

    public JSONValue convertMapToJsonObject(Map<String, ? extends Object> values) {
        if (values == null) {
            return JSONNull.getInstance();
        }
        JSONObject value = new JSONObject();
        for (Map.Entry<String, ? extends Object> entry : values.entrySet()) {
            String string = entry.getKey();
            Object entryValue = entry.getValue();
            value.put(string, toObjectJson(entryValue));
        }
        return value;
    }

    public RequestBuilder buildRequest(String server, String method) {
//        String url = "http://chapolinekarine.com.br/Server/server/service/" + server + "/" + method;
        String url = "/Server/server/service/" + server + "/" + method;

        RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));

        builder.setHeader("Content-Type", "application/json");
        builder.setHeader("Accept", "application/json");
        return builder;
    }

    public void sendRequest(String servidor, String method, String parametros, RequestCallback callBack) {
        try {
            buildRequest(servidor, method).sendRequest(parametros, callBack);
        } catch (RequestException ex) {
            GWT.log("Error in request!", ex);
        }
    }

    public void sendRequest(String servidor, String method, JSONArray parametros, RequestCallback callBack) {
        try {
            buildRequest(servidor, method).sendRequest(parametros.toString(), new MyRequestCallback(callBack));
        } catch (RequestException ex) {
            Logger.getLogger(HanRequestBuilder.class.getName()).log(Level.SEVERE, "Error request", ex);
        }
    }

    public class MyRequestCallback implements RequestCallback {

        private final RequestCallback callBack;

        public MyRequestCallback(RequestCallback callBack) {
            this.callBack = callBack;
        }

        @Override
        public void onResponseReceived(Request request, Response response) {
            if (response.getStatusCode() == 419) { // session time out code
            } else {
                if (callBack != null) {
                    callBack.onResponseReceived(request, response);
                }
            }
        }

        @Override
        public void onError(Request request, Throwable exception) {
        }
    }

    private String getStringValue(JSONValue value) {
        JSONValue retorno;
        if ((retorno = value.isObject()) != null) {
            return retorno.toString();
        } else if ((retorno = value.isArray()) != null) {
            return retorno.toString();
        } else if ((retorno = value.isString()) != null) {
            return ((JSONString) retorno).stringValue();
        } else if ((retorno = value.isBoolean()) != null) {
            return Boolean.toString(((JSONBoolean) retorno).booleanValue());
        } else if ((retorno = value.isNumber()) != null) {
            return Double.toString(((JSONNumber) retorno).doubleValue());
        } else { //JSONNull
            return null;
        }
    }
}
